Skip to content

Feature/builder errors#27

Merged
joelbenway merged 11 commits intomasterfrom
feature/builder-errors
Nov 27, 2025
Merged

Feature/builder errors#27
joelbenway merged 11 commits intomasterfrom
feature/builder-errors

Conversation

@joelbenway
Copy link
Copy Markdown
Owner

@joelbenway joelbenway commented Nov 27, 2025

Summary by CodeRabbit

  • New Features

    • Added IsValid() method for checking builder configuration validity
  • Documentation

    • Updated README with refined emoji styling and references
    • Refined Code of Conduct formatting for improved clarity
  • Tests

    • Expanded test coverage with new validation scenarios, comprehensive parameterization, and additional test fixtures across multiple configurations

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 27, 2025

Walkthrough

This PR adds a public IsValid() validation method to the Builder class, refactors documentation formatting in CODE_OF_CONDUCT and README, and significantly expands ballistic spin-drift test coverage with new fixture parameters, Boatright model variants, and enhanced validation assertions.

Changes

Cohort / File(s) Summary
Documentation & Metadata
CODE_OF_CONDUCT.md, README.md
Reformatted Scout Law bullet list (removed trailing commas and "and" conjunction); replaced US flag emojis with statue-of-liberty and eagle emojis in descriptive text and license notice.
Builder Public API
include/lob/lob.hpp, source/lob_builder.cpp
Exposed public bool IsValid() const method in Builder class; refactored private ValidateBuild() to public validation logic; Build() now invokes IsValid() before proceeding.
Ballistic Spin-Drift Tests
test/source/lob_cwaj_test.cpp, test/source/lob_spin_drift_test.cpp
Added fixture constants for bullet geometry (kZeroDistance, kBarrelTwist, kOgiveLength, kTailLength, kMeplatDiameter, kBaseDiameter, kRtR); expanded test cases with Litz and Boatright model variants; updated expected solution values; added per-entry validation loops for aerodynamic-jump, velocity, energy, and MOA conversions; renamed test cases with descriptive model prefixes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~90 minutes

  • test/source/lob_cwaj_test.cpp: Extensive fixture parameterization and new test cases with multiple wind/spin combinations require verification of updated ballistic calculations and expected values across ~10+ test scenarios.
  • test/source/lob_spin_drift_test.cpp: Comprehensive test expansion including renamed cases (Litz/Boatright prefixes), new geometry parameters, and per-entry validation loops demand careful cross-checking of numerical tolerances and assertion logic.
  • source/lob_builder.cpp: Validation logic refactoring from private to public requires verification that error-state handling (kNotFormed, kNone, field validation) remains consistent with Build() workflow.
  • Numerical data consistency: Multiple expected values across test files (velocity, energy, elevation, deflection, time_of_flight) have been updated; review should confirm they align with the ballistic model updates.

Possibly related PRs

  • Add error handling to Builder #25: Modifies Builder validation surface and Build/Reset logic—directly related to the IsValid() public method exposure and validation refactoring.
  • Update CODE_OF_CONDUCT.md #26: Reformats CODE_OF_CONDUCT.md Scout Law section—parallel documentation formatting changes.
  • boatright spin drift #22: Modifies ballistic/spin-drift subsystem and aerodynamic-jump logic—relates to the extended test coverage for Litz and Boatright spin-drift models.

Poem

🐰 A builder's strength now shown so clear,
With IsValid() standing here—
Through Litz and Boatright models we bound,
Where spin-drift truths are finally found.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Feature/builder errors' is too vague and generic. While it references the builder concept present in the code changes, it does not clearly convey what specific feature or improvement was implemented. Use a more descriptive title that clearly indicates the specific feature added, such as 'Add IsValid() validation method to Builder class' or similar.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/builder-errors

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Nov 27, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
test/source/lob_spin_drift_test.cpp (2)

25-30: Fixture constants could be static constexpr.

These constants are identical across all test instances. Declaring them as static constexpr would be slightly more efficient and clearer in intent:

-  const double kZeroDistance = 300;
-  const double kOgiveLength = 0.748;
-  const double kTailLength = 0.257;
-  const double kMeplatDiameter = 0.069;
-  const double kBaseDiameter = 0.276;
-  const double kRtR = 0.99;
+  static constexpr double kZeroDistance = 300;
+  static constexpr double kOgiveLength = 0.748;
+  static constexpr double kTailLength = 0.257;
+  static constexpr double kMeplatDiameter = 0.069;
+  static constexpr double kBaseDiameter = 0.276;
+  static constexpr double kRtR = 0.99;

114-135: Consider extracting common verification logic.

The verification loop pattern is repeated identically across 9+ tests. While inline assertions are often preferred in tests for clearer failure messages, this level of duplication could be reduced with a helper function:

void VerifySolutions(const std::array<lob::Output, N>& solutions,
                     const std::vector<lob::Output>& expected,
                     uint16_t velocity_error, uint16_t energy_error,
                     double moa_error, double inch_error, double tof_error);

This is optional since the current approach provides explicit, readable test output on failures.

test/source/lob_cwaj_test.cpp (2)

114-135: Consider extracting the validation loop into a helper function.

The solution validation pattern (comparing range, velocity, energy, elevation MOA/inches, deflection MOA/inches, time_of_flight) is repeated across 10+ tests. A helper like ExpectSolutionNear(solutions, expected, tolerances) would reduce duplication and centralize tolerance definitions.

Example approach:

void ExpectSolutionsNear(
    const std::span<const lob::Output> solutions,
    const std::span<const lob::Output> expected,
    uint16_t velocity_err, uint16_t energy_err,
    double moa_err, double inch_err, double tof_err) {
  ASSERT_EQ(solutions.size(), expected.size());
  for (size_t i = 0; i < solutions.size(); ++i) {
    EXPECT_EQ(solutions[i].range, expected[i].range);
    EXPECT_NEAR(solutions[i].velocity, expected[i].velocity, velocity_err);
    // ... remaining assertions
  }
}

740-741: Verify if the commented-out kSMK168 test case should be tracked.

This test case is excluded but the reason isn't documented. Consider adding a comment explaining why it's disabled, or creating an issue to investigate if it should be enabled.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a7c8a22 and 0cb6243.

📒 Files selected for processing (6)
  • CODE_OF_CONDUCT.md (1 hunks)
  • README.md (2 hunks)
  • include/lob/lob.hpp (1 hunks)
  • source/lob_builder.cpp (2 hunks)
  • test/source/lob_cwaj_test.cpp (11 hunks)
  • test/source/lob_spin_drift_test.cpp (11 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-04-15T13:11:22.842Z
Learnt from: joelbenway
Repo: joelbenway/lob PR: 15
File: source/calc.hpp:52-52
Timestamp: 2025-04-15T13:11:22.842Z
Learning: In lob, the `CalculateProjectileReferenceArea` function returns area in square inches (SqInT), but in some calculations like those in test/source/calc_test.cpp, this value is intentionally converted to square feet (SqFtT) when multiplied by air density in pounds per cubic foot (LbsPerCuFtT) to ensure proper unit cancellation.

Applied to files:

  • test/source/lob_spin_drift_test.cpp
  • README.md
  • test/source/lob_cwaj_test.cpp
📚 Learning: 2025-06-17T12:55:26.522Z
Learnt from: joelbenway
Repo: joelbenway/lob PR: 25
File: include/lob/lob.hpp:123-130
Timestamp: 2025-06-17T12:55:26.522Z
Learning: In the lob ballistics library, when Input::step_size is set to 0 (the default), the solver automatically sets an appropriate step size internally rather than failing with an assertion error.

Applied to files:

  • test/source/lob_spin_drift_test.cpp
  • README.md
  • test/source/lob_cwaj_test.cpp
📚 Learning: 2025-05-22T16:12:16.630Z
Learnt from: joelbenway
Repo: joelbenway/lob PR: 22
File: test/source/boatright_test.cpp:58-65
Timestamp: 2025-05-22T16:12:16.630Z
Learning: In the lob codebase, std::pow and potentially other standard library functions have been overloaded to work directly with strong types (like InchT, CaliberT, etc.), allowing expressions like std::pow(kD / 2, 2) to compile correctly without needing to extract the underlying value first.

Applied to files:

  • README.md
📚 Learning: 2025-05-23T12:16:39.175Z
Learnt from: joelbenway
Repo: joelbenway/lob PR: 22
File: source/boatright.cpp:72-81
Timestamp: 2025-05-23T12:16:39.175Z
Learning: In the lob codebase, std::pow has been overloaded in eng_units.hpp to work directly with strong unit types (like InchT, CaliberT, etc.), allowing expressions like std::pow(diameter / 2, 2) to compile correctly without needing to extract raw values using the Value() method.

Applied to files:

  • README.md
📚 Learning: 2025-05-23T20:47:45.448Z
Learnt from: joelbenway
Repo: joelbenway/lob PR: 22
File: source/lob_solve.cpp:0-0
Timestamp: 2025-05-23T20:47:45.448Z
Learning: In lob_solve.cpp, the loop pattern that accesses pranges[index] is safe from out-of-bounds access because it checks if (index >= size) and breaks immediately after incrementing index, ensuring pranges[index] is never accessed with an invalid index.

Applied to files:

  • test/source/lob_cwaj_test.cpp
🧬 Code graph analysis (2)
test/source/lob_spin_drift_test.cpp (1)
source/lob_convert.cpp (2)
  • InchToMoa (39-44)
  • InchToMoa (39-39)
source/lob_builder.cpp (1)
include/lob/lob.hpp (1)
  • IsValid (445-445)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: test (ubuntu-latest, shared)
  • GitHub Check: test (ubuntu-latest, static)
  • GitHub Check: test (windows-latest, static)
  • GitHub Check: test (windows-latest, shared)
  • GitHub Check: test (macos-latest, shared)
  • GitHub Check: test (macos-latest, static)
  • GitHub Check: sanitize
  • GitHub Check: coverage
🔇 Additional comments (14)
README.md (1)

28-28: LGTM!

The emoji updates are consistent throughout the document—replacing the US flag references with statue of liberty and eagle emojis.

Also applies to: 139-139

CODE_OF_CONDUCT.md (1)

9-20: LGTM!

The bullet list formatting is now cleaner and more consistent without trailing commas.

include/lob/lob.hpp (1)

441-445: LGTM!

The new IsValid() public API is well-documented and properly declared as const. This provides a useful validation query before calling Build().

source/lob_builder.cpp (2)

432-441: LGTM!

The IsValid() implementation correctly validates the minimum required inputs:

  • Error state is acceptable (not a previous validation failure)
  • Ballistic coefficient is set
  • Velocity is set (non-zero)
  • Either zero distance or zero angle is provided

This aligns with the minimal example in the README where only BC, velocity, and zero distance are required.


783-805: LGTM!

The Build() integration with IsValid() is well-structured:

  1. Resets error state to kNotFormed if previously successful (allows re-building)
  2. Validates via IsValid() before proceeding
  3. Executes build steps in correct dependency order
  4. Marks error as kNone on successful completion
test/source/lob_spin_drift_test.cpp (2)

8-8: LGTM!

The <cmath> include is necessary for std::isnan() used in the spindrift_factor validation assertions.


370-432: Comprehensive Boatright model test coverage.

The new Boatright tests appropriately:

  • Configure all required ogive parameters (nose length, tail length, base diameter, meplat diameter, RtR)
  • Verify spindrift_factor is non-NaN (confirming Boatright path was taken)
  • Test both right-hand and left-hand twist with standard and fast twist rates

The distinction between Litz (NaN spindrift_factor) and Boatright (non-NaN spindrift_factor) tests provides clear validation that the correct calculation path is being exercised.

test/source/lob_cwaj_test.cpp (7)

25-31: LGTM: Centralized fixture constants improve test maintainability.

Good refactoring to extract these shared parameters as fixture-level constants, ensuring consistency across all spin/wind scenario tests.


38-43: Well-documented test data source.

Citing the reference (Litz, pg 656) makes it easier to verify expected values and understand the test scenario.


64-72: LGTM!

Using the fixture constant kZeroDistance ensures consistency with the other tests.


83-136: Test data looks physically consistent.

The SolveWithoutSpin test correctly shows zero deflection at all ranges (no spin drift without twist parameter), with expected velocity decay and trajectory drop. The validation loop thoroughly checks all solution attributes.


139-199: Litz model tests demonstrate correct symmetry.

The aerodynamic jump values (±0.650208) correctly flip signs for opposite twist directions. Deflection values appropriately become more negative with left-hand spin in leftward wind conditions.


392-458: LGTM: Boatright model tests properly utilize extended bullet geometry.

The additional parameters (NoseLengthInch, TailLengthInch, BaseDiameterInch, MeplatDiameterInch, OgiveRtR) correctly enable the Boatright aerodynamic jump calculation, producing a higher magnitude (1.015683 vs 0.650208 for Litz) as expected from the more detailed model.


695-712: LGTM!

The parameterized Boatright test correctly validates the aerodynamic jump calculation against expected values with 10% tolerance, accounting for variations in the model.

@joelbenway joelbenway merged commit f194e68 into master Nov 27, 2025
12 checks passed
@joelbenway joelbenway deleted the feature/builder-errors branch November 27, 2025 03:15
@coderabbitai coderabbitai Bot mentioned this pull request Dec 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant